AddCSLuaFile("cl_init.lua") 
AddCSLuaFile("shared.lua") 
include('shared.lua')



ENT.TrackIndexTriggerInformation = {}

local STATE_STOPPED = 0
local STATE_PAUSED = 2
local STATE_PLAYING = 1

function ENT:Initialize() 
	self.BaseClass.Initialize(self, nil)
	
	self.TransitionAnimation = "Walk" //1 = walk (animation.lua)
	self.AnimationSequence = {}
	self.PlayState = 0

    self.OwnedActors = {}
	self.VisitingActors = {}
end


/*************************************************
 * Allows animation data to be assigned to this waypoint
 * This data is applied to all NPC's that visit the waypoint
 *************************************************/	
function ENT:UpdateAnimationData(animationSequence, transitionAnimation)

	self.AnimationSequence = animationSequence or {};
	self.TransitionAnimation = transitionAnimation or "Walk";	//1 = walk (animation.lua)

end

function Remove(object, list)

	if object and list then

		local newList = {}
		for k,o in pairs(list) do
			if o != object then
				table.insert(newList, o)
			end
		end

		return newList
	end

	return list
end

function ENT:ReleaseVisitingActors()

	if self.VisitingActors and #self.VisitingActors > 0 then
		for actKey, actObj in pairs(self.VisitingActors) do
			if actObj then
				actObj.Actor = nil
				actObj.AnimationSequence:Release()
				actObj.AnimationSequence:Remove()
				actObj.AnimationSequence = nil
			end
		end
	end
	self.VisitingActors = {}
end

function ENT:ReleaseVisitingActor(visitor)

	if visitor == nil then
		return
	end

	local newActorsList = {}
	for actKey, actObj in pairs(self.VisitingActors) do

		if actObj.Actor != visitor.Actor then
			table.insert(newActorsList, actObj)
		else
			visitor.Actor = nil
			visitor.AnimationSequence:Release()
			visitor.AnimationSequence:Remove()
			visitor.AnimationSequence = nil
		end

	end
	self.VisitingActors = newActorsList
end

///////////////////////////////////////////////////////////
function ENT:SetVisitingActor(actor, offset)

	for _, va in pairs(self.VisitingActors) do
		if va.Actor == actor then
			return
		end
	end
	
	local actorOffset = self:GetPos() - actor:GetPos()
	local ScriptSequence = ents.Create("animation_sequence")
	ScriptSequence:Spawn()
	ScriptSequence:SetPos(self:GetPos())
    ScriptSequence:ActorExecute(actor, self.AnimationSequence, self.TransitionAnimation or "Walk", offset)  

	table.insert(self.VisitingActors, {Actor = actor, Offset = offset, AnimationSequence = ScriptSequence})
end

function ENT:Think()
	if self.PlayState == 1 then
		self:ThinkActors()
	end

	self.Entity:NextThink(CurTime() + 10)
end

//****************************************************
//* Called on a per frame basis, this iterates all actors
//* of the current node to see if any should be passed onto
//* a subsequent node
function ENT:ThinkActors()

	if self.VisitingActors == nil or #self.VisitingActors == 0 then
		return
	end

	local nextNode = self.BaseClass.GetNextNode(self)
	for vak, vao in pairs(self.VisitingActors) do

		local actor = vao;

		if vao.AnimationSequence.IsComplete == true then

			if actor.Actor and actor.Actor:IsValid() then

				local holdActor = actor.Actor
				local holdOffset = actor.Offset
				self:ReleaseVisitingActor(actor)

				if nextNode and nextNode:IsValid() then
					nextNode:SetVisitingActor(holdActor, holdOffset)
				else
					//we must be at the end
					local rootNode = GetRootNode(self)
					print(holdActor, " finished animation")
					print("self = ",self)
					print("root = ",rootNode)

					local schedulePosition = rootNode:GetPos() + holdOffset

	  				holdActor:SetSchedule(SCHED_NONE)
					holdActor:SetPos(schedulePosition)
					holdActor:SetLastPosition(schedulePosition)

				end
			end
		end
	end
end

function ENT:SetPlayState(playState)

	local nextNode = self.BaseClass.GetNextNode(self)
	if not (nextNode and nextNode:IsValid()) then
		return
	end

	local currentNode = self
	while true do
		currentNode.PlayState = playState
		local next = self.BaseClass.GetNextNode(currentNode)
		if next and next:IsValid() then
			currentNode = next
		else
			break
		end
	end
	
	//Playing
	if self.PlayState == 1 then
		for ak, ao in pairs(self.OwnedActors) do
			self:SetVisitingActor(ao.Actor, ao.Offset)
		end
	//Stoped
	else
		local rootNode = GetRootNode(self)
		local stopNode = rootNode
		while true do
			stopNode:ReleaseVisitingActors()
			stopNode.PlayState = 0
			local next = self.BaseClass.GetNextNode(stopNode)
			if next and next:IsValid() then
				stopNode = next
			else
				break
			end
		end
	
		for ak, ao in pairs(self.OwnedActors) do
			ao.Actor:SetPos(rootNode:GetPos() + ao.Offset)
			ao.Actor:SetLastPosition(rootNode:GetPos() + ao.Offset)
			ao.Actor:SetSchedule(SCHED_NONE )
		end
	end
end

function ENT:OnDelete()
	self:ReleaseVisitingActors()
	self.OwnedActors = {}
end

function ENT:UpdateActors(newActors)
	self.OwnedActors = {}

	if newActors then
		for iK,iAct in pairs(newActors) do
			if iAct and iAct:IsValid() then
				table.insert(self.OwnedActors, {Actor = iAct, Offset = iAct:GetPos() - self:GetPos()})
			end
		end
	end
	
end

//****************************************************
//*	Enables an NPC/actor to be assigned to an actor
//* pathway. This will by default send the actor to the
//* first node. This should not typically be used for 
//* acutal animation of the actor when walking the path
function ENT:AssignActor(actor)
	if actor and actor:IsNPC() then
		for _, currentActor in pairs(self.OwnedActors) do
			if actor == currentActor.Actor then
				return
			end
		end
		table.insert(self.OwnedActors, {Actor = actor, Offset = actor:GetPos() - self:GetPos()})
	end
end

function ENT:PhysicsUpdate(physobj)
	if not self.Entity:IsPlayerHolding() then
		physobj:Sleep()
	end
end